/*
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  Author: hakanai
 *
 */

#pragma once
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#if __has_include("esp_idf_version.h")
#include "esp_idf_version.h"
#include <esp_err.h>
#include <esp_log.h>
#endif

#define SDB_VERBOSE 1

#ifdef ESP_IDF_VERSION
#define SDB_OK ESP_OK
#define SDB_FAIL ESP_FAIL
#define SDB_LOGE(...) ESP_LOGE("SDB", __VA_ARGS__);
#define SDB_LOGI(...) ESP_LOGI("SDB", __VA_ARGS__);
#else
#define SDB_OK 0
#define SDB_FAIL -1
#define SDB_LOGE(...) do { fprintf(stderr,  __VA_ARGS__); fprintf(stderr, "\n"); } while(0)
#define SDB_LOGI(...) do { fprintf(stdout,  __VA_ARGS__); fprintf(stdout, "\n"); } while(0)
#endif // ESP_IDF_VERSION


#ifdef SDB_VERBOSE
#define SDB_ASSERT(c) if (c) { \
  SDB_LOGE("%s:%d SDB_ASSERT(%s)",  __FILE__, __LINE__, #c); \
  return SDB_FAIL; \
}
#else
#define SDB_ASSERT(c) if (c) { \
  return SDB_FAIL; \
}
#endif

#define SDB_HEADER_SIZE 18

typedef struct __attribute__((__packed__)) sdb_header_t {
  uint8_t head[5];
  uint8_t lock;
  uint16_t r_size;
  uint32_t r_num;
  uint32_t size;
  uint16_t crc;
} sdb_header_t;

typedef struct __attribute__((__packed__)) sdb_record_t {
  void *data;
  uint16_t crc;
} sdb_record_t;

typedef struct sdb_t {
  /*
   * In case fcntl() is not available
   */
  char filename[32];
  int fd;
} sdb_t;

int sdb_open(char *filename, sdb_t *db);
int sdb_close(sdb_t *db);
int sdb_create_header(sdb_header_t *heder);
int sdb_write_header(sdb_t *db, sdb_header_t *header);
int sdb_read_header(sdb_t *db, sdb_header_t *header);

int sdb_set_lock(sdb_t *db, int l);
bool sdb_get_lock(sdb_t *db);

int sdb_append(sdb_t *db, void *data, int size);
int sdb_read(sdb_t *db, uint32_t num, void *data);
int sdb_update(sdb_t *db, uint32_t num, void *data);
int sdb_delete(sdb_t *db, uint32_t num);
int sdb_size(sdb_t *db);

uint16_t crc16(const char *buf, int len);

